package com.example.demo.util;

import org.apache.commons.lang3.exception.ExceptionUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

public class AESUtil {

    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
    public static final String CONFIG_PREFIX = "ic.v!";
    private final String key;

    public AESUtil(String key) {
        this.key = key;
    }

    /**
     * 加密字符串
     *
     * @param content
     * @return
     */
    public String encrypt(String content) {
        byte[] encrypt = encrypt(content.getBytes(StandardCharsets.UTF_8), new SecretKeySpec(key.getBytes(), "AES"));
        return CONFIG_PREFIX + Base64.getEncoder().encodeToString(encrypt);
    }

    /**
     * 解密字符串
     *
     * @param content
     * @return
     */
    public String decrypt(String content) {
        if (content.startsWith(CONFIG_PREFIX)) {
            content = content.substring(CONFIG_PREFIX.length());
        }
        byte[] decode = Base64.getDecoder().decode(content);
        byte[] decrypt = decrypt(decode, new SecretKeySpec(key.getBytes(), "AES"));
        return new String(decrypt, StandardCharsets.UTF_8);
    }


    public byte[] encrypt(byte[] data, Key key) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            byte[] iv = SecureRandomRandoms.randBytes(cipher.getBlockSize());
            //初始化密钥与加密参数iv
            cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
            //加密
            byte[] encryptBytes = cipher.doFinal(data);
            //将iv与密文拼在一起
            ByteArrayOutputStream baos = new ByteArrayOutputStream(iv.length + encryptBytes.length);
            baos.write(iv);
            baos.write(encryptBytes);
            return baos.toByteArray();
        } catch (Exception e) {
            return ExceptionUtils.rethrow(e);
        }
    }

    public byte[] decrypt(byte[] data, Key key) {
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            //获取密文前面的iv
            IvParameterSpec ivSpec = new IvParameterSpec(data, 0, cipher.getBlockSize());
            cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
            //解密iv后面的密文
            return cipher.doFinal(data, cipher.getBlockSize(), data.length - cipher.getBlockSize());
        } catch (Exception e) {
            return ExceptionUtils.rethrow(e);
        }
    }

    public static class SecureRandomRandoms {
        public static byte[] randBytes(int len) throws NoSuchAlgorithmException {
            byte[] bytes = new byte[len];
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.nextBytes(bytes);
            return bytes;
        }
    }

    public static void main(String[] args) {
        String hello = new AESUtil("12345678abcdefgh").encrypt("hello");
        System.out.println(hello);
        String hello2 = new AESUtil("12345678abcdefgh").decrypt(hello);
        System.out.println(hello2);
    }
}
